`timescale 1ns / 1ps

module elevator#(parameter floor = 40)( 
    input                                               clk , rst_n, 
    input                                               key , [7:0]H,[3:0]num, [9:0]weight, //紧急按键，是一个脉冲信号,H目标楼层，num人数，weight体重
    output  reg     [7:0]                               N   , //当前楼层
    output                                              alert   //警报信号
); 

assign alert = (num>13 || weight>=1000) ? 1:0 ;

reg [0:0] key_reg;

//状态机
parameter idle = 3'd0;
parameter check = 3'd1;
parameter run_up = 3'd2;
parameter run_down = 3'd3;

reg [2:0] cur_status;
reg [2:0] next_status;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        key_reg <= 1'b0;
    else begin
        if (key)
            key_reg <= 1'b1;
         else begin
            if (next_status <= 0 && cur_status <= 0)
                key_reg <= 1'b0;
                else
                    key_reg <= key_reg;
         end
    end
end

//第一段
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cur_status <= idle;      
        next_status <= idle; 
    end
    else
        cur_status <= next_status;
end

//第二段，状态转移
always @(posedge clk or negedge rst_n) begin
    case (cur_status)
        idle:
            begin
                if(N != H) //如果输入的层数和当前层数不同，则开始检测
                    next_status <= check;
                else
                    next_status <= idle;
            end
        check:
            begin
                if(H>=2 && H<=9)begin
                    if(key_reg) begin
                        if(N < H)
                        next_status <= run_up;
                        else
                        next_status <= run_down;
                    end
                    else
                        next_status <= check;
                end
                else begin
                    if(N < H)
                        next_status <= run_up;
                    else
                        next_status <= run_down;
                end
            end
        run_up:
            begin
                if(N >= H-2)
                    next_status <= idle;
                else
                    next_status <= cur_status;
            end
        run_down:
            begin
                if(N <= H+2)
                    next_status <= idle;
                else
                    next_status <= cur_status;
            end
        default:
            next_status <= idle;
    endcase
end

//第三段 输出
always @(posedge clk or negedge rst_n)begin
    if (!rst_n)
        N <= 0;
    else begin
        case (cur_status)
            idle: 
                begin
                    N <= N;
                end 
            check:
                begin
                    N <= N;
                end 
            run_up:
                begin
                    N <= N+1'b1;
                end 
            run_down:
                begin
                    N <= N-1'b1;
                end    
            default: 
                begin
                    N <= N;
                end 
        endcase
    end
end


endmodule
